package cn.itsource.wechat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.itsource.bean.LoginInfo;
import cn.itsource.bean.User;
import cn.itsource.mapper.UserMapper;
import cn.itsource.service.IUserService;
import cn.itsource.util.JsonResult;
import cn.itsource.util.Md5Password;
import cn.itsource.util.MyUtils;
import cn.itsource.wechat.bean.*;
import cn.itsource.wechat.mapper.WeChatMapper;
import cn.itsource.wechat.service.IWeChatService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

import static cn.itsource.util.RedisContants.*;

/**
 * @author : 张金铭
 * @description :
 * @create :2022-11-18 10:32:00
 */
@Slf4j
@Service
public class WeChatServiceImpl extends ServiceImpl<WeChatMapper, WeChatUser> implements IWeChatService {

    @Resource
    private WechatProperties wechatProperties;

    @Resource
    private IUserService userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserMapper userMapper;


    @Override
    public String tologin() {
        String authorizationCodeUrl = wechatProperties.getAuthorizationCodeUrl();
        //https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect
        String appId = wechatProperties.getAppId();
        String redirectUri = wechatProperties.getRedirectUri();
        String state = IdUtil.fastSimpleUUID();

        authorizationCodeUrl = String.format(authorizationCodeUrl, appId, redirectUri);

//        log.info("url:{}",authorizationCodeUrl);

        return  authorizationCodeUrl;
    }

    @Override
    public String callback(String code) {
        //1.拿到获取token的url %s
        String tokenUrl = wechatProperties.getTokenUrl();
        //https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code
        log.info(tokenUrl);

        String appId = wechatProperties.getAppId();
        String appSecrect = wechatProperties.getAppSecrect();

        //2.替换%s
        tokenUrl = String.format(tokenUrl, appId, appSecrect, code);
        log.info(tokenUrl);

        //3.发get请求获取结果
        String result = HttpUtil.get(tokenUrl);
        System.out.println(result);

        //4.把json字符串转成对象
        WechatTokenDto wechatTokenDto = JSONObject.parseObject(result, WechatTokenDto.class);
        System.out.println(wechatTokenDto.getAccess_token());

        /** 第三步骤：通过token拿到用户资源（微信用户信息）*/
        //1.拿到userInfo的url
        String userinfoUrl = wechatProperties.getUserinfoUrl();
        String access_token = wechatTokenDto.getAccess_token();
        String openid = wechatTokenDto.getOpenid();
        //2.替换%s
        userinfoUrl = String.format(userinfoUrl,access_token,openid);

        //3.发送get请求获取结果
        String userInfoResult = HttpUtil.get(userinfoUrl);
        System.out.println(userInfoResult);

        //4.转成对象
        WechatUserInfoDto wechatUserInfoDto = JSONObject.parseObject(userInfoResult, WechatUserInfoDto.class);

        //5.查询数据库中是否存在该微信用户
        LambdaQueryWrapper<WeChatUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Strings.isNotEmpty(openid),WeChatUser::getOpenid,openid);
        WeChatUser weChatUser = this.getOne(queryWrapper);



        //5.1情况一，微信表不存在,插入到微信表，并未绑定用户，携带openid跳转到绑定手机号
        if (weChatUser==null){
            WeChatUser wxUser = BeanUtil.copyProperties(wechatUserInfoDto, WeChatUser.class);
            this.save(wxUser);
            return "http://localhost:8081/binder.html?openid="+openid;
        }else {
            //5.2情况二，微信表存在该用户，并未绑定用户，携带openid跳转到绑定手机号
            Long userId = weChatUser.getUserId();
            User user = userService.getById(userId);
            if (user==null){
            return "http://localhost:8081/binder.html?openid="+openid;
            }
        }
        Long userId = weChatUser.getUserId();
        User user = userService.getById(userId);
        //5.3情况三，微信已经已绑定用户，跳转到首页，并携带token和用户基础信息
        //将雇员对象转换为json存储
        String token = cn.hutool.core.lang.UUID.randomUUID().toString(true);
        LoginInfo loginInfo = loginKey(user, stringRedisTemplate,token);

        return "http://bugtracker.itsource.cn:8081/index.html?token="+token
                +"&username="+ StringUtils.defaultIfBlank(user.getUsername(),"")+"&email="+StringUtils.defaultIfBlank(user.getEmail(),"")+
                "&phone="+StringUtils.defaultIfBlank(user.getPhone(),"");
    }



    //获取到验证码
    @Override
    public JsonResult binder(WeChatDto user) {
        String phone = user.getPhone();
        //将发送来的号码进行验证
        if (!MyUtils.isValidPhoneNumber(phone)) {
            return JsonResult.error("手机格式不正确");
        }

        String codeKey = USER_PHONE_CODE+phone;

        //将发过来的验证码进行验证
//        String code = stringRedisTemplate.opsForValue().get(codeKey);
//        if (Strings.isEmpty(code)){
//            return JsonResult.error("验证码不能为空");
//        }
//        if (!user.getCode().equals(code)){
//            return JsonResult.error("验证码输入错误");
//        }

        //将手机号在数据库进行查查询
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone,phone);
        User dbUser = userService.getOne(queryWrapper);
        Long userId = dbUser.getId();

        //查询微信用户
        String openid = user.getOpenid();
        if (Strings.isEmpty(openid)){
            return JsonResult.error("微信验证过期,请重新扫码");
        }
        LambdaQueryWrapper<WeChatUser> weChatUserQueryWrapper = new LambdaQueryWrapper<>();
        weChatUserQueryWrapper.eq(WeChatUser::getOpenid,openid);
        WeChatUser weChatUser = this.getOne(weChatUserQueryWrapper);

        if (weChatUser==null){
            return JsonResult.error("微信验证过期,请重新扫码");
        }


        Long wxUserId = null;
        //判断
        if (dbUser==null){
            //为该账号默认一个加盐的密码
            String salt = MyUtils.getSalt();
            String md5Password = Md5Password.getMd5Password(phone, salt);
            dbUser = new User();
            dbUser.setSalt(salt);
            dbUser.setPassword(md5Password);
            dbUser.setPhone(phone);
            //存入user，并获取id
            userMapper.insert(dbUser);
            wxUserId = dbUser.getId();
            //获取id后将微信用户表绑定该用户
            weChatUser.setUserId(wxUserId);
            this.updateById(weChatUser);
            //存入缓存，拿出令牌
            String token = cn.hutool.core.lang.UUID.randomUUID().toString(true);
            LoginInfo loginInfo = loginKey(dbUser, stringRedisTemplate,token);
            return JsonResult.success("绑定成功",loginInfo);
        } else {//该用户存在，将微信用户表绑定userid
            //拿出微信用户id
            wxUserId = dbUser.getId();
            LambdaQueryWrapper<WeChatUser> weChatUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            weChatUserLambdaQueryWrapper.eq(WeChatUser::getUserId,userId);
            WeChatUser chatUser = this.getOne(weChatUserLambdaQueryWrapper);
            //若该用户已绑定用户，则将之前的用户解绑
            if (chatUser!=null){
                chatUser.setUserId(null);
                this.updateById(chatUser);
            }
            //该user未绑定用户
            weChatUser.setUserId(wxUserId);
            this.updateById(weChatUser);
            String token = cn.hutool.core.lang.UUID.randomUUID().toString(true);
            LoginInfo loginInfo = loginKey(dbUser, stringRedisTemplate,token);
            return JsonResult.success("绑定成功",loginInfo);
        }
    }



    public static LoginInfo loginKey(User dbUser,StringRedisTemplate stringRedisTemplate,String token){
        LoginInfo loginInfo = BeanUtil.copyProperties(dbUser,LoginInfo.class);
        loginInfo.setId(dbUser.getId());
        String jsonUser = JSONUtil.toJsonStr(loginInfo);
        //生成一个token，作为登入令牌               true带下划线的UUID
        String key = LOGIN_USER_KEY +token;
        loginInfo.setToken(token);
        //6.将userDao存入redis
        stringRedisTemplate.opsForValue().set(key,jsonUser,LOGIN_USER_TTL, TimeUnit.MINUTES);
        //存入后将id清除
        loginInfo.setId(null);
        return loginInfo;
    }
}
